﻿using System;
using System.Drawing;

using System.IO;
using System.Web;


namespace Matrix.Common.Utility.Files
{
    /// <summary>
    /// 文件操作类
    /// </summary>
    public class ImagesFile
    {
        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="originalImagePath">源图路径（物理路径）</param>
        /// <param name="thumbnailPath">缩略图路径（物理路径）</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="mode">生成缩略图的方式</param>
        public void CutPic(string originalImagePath, string thumbnailPath, int width, int height, string mode = "Cut")
        {
            int i_Width = 0, i_Height = 0;
            //string strPicPath = HttpContext.Current.Server.MapPath(originalImagePath);
            string strPicPath = originalImagePath;
            Image uImage = Image.FromFile(strPicPath);
            i_Width = uImage.Width < width ? uImage.Width : width;
            i_Height = uImage.Height < height ? uImage.Height : height;
            uImage.Dispose();

            width = i_Width;
            height = i_Height;

            //originalImagePath = HttpContext.Current.Server.MapPath(originalImagePath);
            //thumbnailPath = HttpContext.Current.Server.MapPath(thumbnailPath);
            var originalImage = Image.FromFile(originalImagePath);

            int towidth = width;
            int toheight = height;

            int x = 0;
            int y = 0;
            int ow = originalImage.Width;
            int oh = originalImage.Height;

            switch (mode)
            {
                case "HW"://指定高宽缩放（可能变形）                
                    break;
                case "W"://指定宽，高按比例
                    if (originalImage.Width < width)
                    {
                        towidth = originalImage.Width;
                        toheight = originalImage.Height;
                    }
                    else
                    {
                        toheight = originalImage.Height * width / originalImage.Width;
                    }
                    break;
                case "H"://指定高，宽按比例
                    if (originalImage.Height < height)
                    {
                        toheight = originalImage.Height;
                        towidth = originalImage.Width;
                    }
                    else
                    {
                        towidth = originalImage.Width * height / originalImage.Height;
                    }
                    break;
                case "Cut"://指定高宽裁减（不变形）                
                    if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight)
                    {
                        oh = originalImage.Height;
                        ow = originalImage.Height * towidth / toheight;
                        y = 0;
                        x = (originalImage.Width - ow) / 2;
                    }
                    else
                    {
                        ow = originalImage.Width;
                        oh = originalImage.Width * height / towidth;
                        x = 0;
                        y = (originalImage.Height - oh) / 2;
                    }
                    break;
                default:
                    break;
            }

            //新建一个bmp图片
            var bitmap = new Bitmap(towidth, toheight);

            //新建一个画板
            var g = Graphics.FromImage(bitmap);

            //设置高质量插值法
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

            //设置高质量,低速度呈现平滑程度
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            //清空画布并以透明背景色填充
            g.Clear(Color.Transparent);

            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),
                new Rectangle(x, y, ow, oh),
                GraphicsUnit.Pixel);

            try
            {
                string path;
                if (thumbnailPath.LastIndexOf("\\", StringComparison.Ordinal) > -1)
                {
                    path = thumbnailPath.Substring(0, thumbnailPath.LastIndexOf('\\'));
                }
                else
                {
                    path = thumbnailPath;
                }

                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                
                //以jpg格式保存缩略图
                bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }
        }

        /// <summary>
        /// 移除文件的只读属性
        /// </summary>
        /// <param name="filePath"></param>
        public void RemoveReadOnly(string filePath)
        {
            filePath = System.Web.HttpContext.Current.Server.MapPath(filePath);

            // 先把文件的属性读取出来 
            FileAttributes attrs = File.GetAttributes(filePath);
            // 下面表达式中的 1 是 FileAttributes.ReadOnly 的值 
            // 此表达式是把 ReadOnly 所在的位改成 0, 
            attrs = (FileAttributes)((int)attrs & ~(1));
            File.SetAttributes(filePath, attrs);
        }

        /// <summary>
        /// 获取目录或者文件的绝对（完全）路径
        /// </summary>
        /// <param name="strPath">目录的相对路径（如：/UploadFile/）</param>
        /// <returns></returns>
        public string GetFullPath(string strPath)
        {
            return System.Web.HttpContext.Current.Server.MapPath(strPath);
        }

        /// <summary>
        /// 检测指定目录是否存在
        /// </summary>
        /// <param name="directoryPath">目录的相对路径（如：/UploadFile/）</param>
        /// <returns></returns>
        public bool IsExistDirectory(string directoryPath)
        {
            return System.IO.Directory.Exists(GetFullPath(directoryPath));
        }

        /// <summary>
        /// 检测指定文件是否存在
        /// </summary>
        /// <param name="filePath">目录的相对路径（如：/UploadFile/demo.txt）</param>
        /// <returns></returns>
        public bool IsExistFile(string filePath)
        {
            return System.IO.File.Exists(GetFullPath(filePath));
        }

        /// <summary>
        /// 获取指定目录中所有文件列表
        /// </summary>
        /// <param name="directoryPath">目录的相对路径（如：/UploadFile/）</param>
        /// <returns></returns>
        public string[] GetFileNames(string directoryPath)
        {
            //如果目录不存在，则抛出异常
            if (!IsExistDirectory(directoryPath))
            {
                throw new System.IO.FileNotFoundException();
            }
            //获取文件列表
            return System.IO.Directory.GetFiles(GetFullPath(directoryPath));
        }

        /// <summary>
        /// 获取指定目录中所有子目录列表（不包含嵌套目录）
        /// </summary>
        /// <param name="directoryPath">目录的相对路径（如：/UploadFile/）</param>
        /// <returns></returns>
        public string[] GetDirectories(string directoryPath)
        {
            try
            {
                return System.IO.Directory.GetDirectories(GetFullPath(directoryPath));
            }
            catch (System.IO.IOException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 获取指定目录及子目录中所有子目录列表
        /// </summary>
        /// <param name="directoryPath">目录的相对路径（如：/UploadFile/）</param>
        /// <param name="searchPattern">模式字符串，"*"代表0或N个字符，"?"代表1个字符。
        /// 范例："Log*.xml"表示搜索所有以Log开头的Xml文件。</param>
        /// <param name="isSearchChild">是否搜索子目录</param>
        /// <returns></returns>
        public string[] GetDirectories(string directoryPath, string searchPattern, bool isSearchChild)
        {
            try
            {
                if (isSearchChild)
                {
                    return System.IO.Directory.GetDirectories(GetFullPath(directoryPath), searchPattern, System.IO.SearchOption.AllDirectories);
                }
                else
                {
                    return System.IO.Directory.GetDirectories(GetFullPath(directoryPath), searchPattern, System.IO.SearchOption.TopDirectoryOnly);
                }
            }
            catch (System.IO.IOException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 获取指定目录及子目录中所有文件列表
        /// </summary>
        /// <param name="directoryPath">目录的相对路径（如：/UploadFile/）</param>
        /// <param name="searchPattern">模式字符串，"*"代表0或N个字符，"?"代表1个字符。
        /// 范例："Log*.xml"表示搜索所有以Log开头的Xml文件。</param>
        /// <param name="isSearchChild">是否搜索子目录</param>
        /// <returns></returns>
        public string[] GetFileNames(string directoryPath, string searchPattern, bool isSearchChild)
        {
            //如果目录不存在，则抛出异常
            if (!IsExistDirectory(directoryPath))
            {
                throw new System.IO.FileNotFoundException();
            }

            try
            {
                if (isSearchChild)
                {
                    return System.IO.Directory.GetFiles(GetFullPath(directoryPath), searchPattern, System.IO.SearchOption.AllDirectories);
                }
                else
                {
                    return System.IO.Directory.GetFiles(GetFullPath(directoryPath), searchPattern, System.IO.SearchOption.TopDirectoryOnly);
                }
            }
            catch (System.IO.IOException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 检测指定目录是否为空
        /// </summary>
        /// <param name="directoryPath">目录的相对路径（如：/UploadFile/）</param>
        /// <returns></returns>
        public bool IsEmptyDirectory(string directoryPath)
        {
            try
            {
                //判断是否存在文件
                string[] fileNames = GetFileNames(directoryPath);
                if (fileNames.Length > 0)
                {
                    return false;
                }
                //判断是否存在文件夹
                string[] directoryNames = GetDirectories(directoryPath);
                if (directoryNames.Length > 0)
                {
                    return false;
                }
                return true;
            }
            catch
            {
                //这里记录日志
                //LogHelper.WriteTraceLog(TraceLogLevel.Error, ex.Message);
                return true;
            }
        }

        /// <summary>
        /// 检测指定目录中是否存在指定的文件（不包含子目录）
        /// </summary>
        /// <param name="directoryPath">目录的相对路径（如：/UploadFile/）</param>
        /// <param name="searchPattern">模式字符串，"*"代表0或N个字符，"?"代表1个字符。
        /// 范例："Log*.xml"表示搜索所有以Log开头的Xml文件。</param>
        /// <returns></returns>
        public bool IsContainsFile(string directoryPath, string searchPattern)
        {
            try
            {
                //获取指定的文件列表
                string[] fileNames = GetFileNames(directoryPath, searchPattern, false);

                //判断指定文件是否存在
                if (fileNames.Length == 0)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
                //LogHelper.WriteTraceLog(TraceLogLevel.Error, ex.Message);
            }
        }

        /// <summary>
        /// 创建目录
        /// </summary>
        /// <param name="directoryPath">要创建的目录名称（如：/UploadFile/2013/06/10/）</param>
        /// <returns></returns>
        public void CreateDirectory(string directoryPath)
        {
            if (directoryPath.Length > 0)
                if (!System.IO.Directory.Exists(GetFullPath(directoryPath)))
                    System.IO.Directory.CreateDirectory(GetFullPath(directoryPath));
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="strDataFilePath"></param>
        public void DeleteFiles(string strDataFilePath)
        {
            if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(strDataFilePath)))
                System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath(strDataFilePath));
        }

        /// <summary>
        /// 创建目录
        /// </summary>
        /// <param name="directoryPath">要创建的目录名称（如：/UploadFile/2013/06/10/）</param>
        /// <returns></returns>
        public void CreateDirectoryOrExist(string directoryPath)
        {
            if (directoryPath.Length > 0)
                if (!System.IO.Directory.Exists(directoryPath))
                    System.IO.Directory.CreateDirectory(directoryPath);
        }

        /// <summary>
        /// 删除目录（删除的目录为空）
        /// </summary>
        /// <param name="directoryPath">要删除的目录名称（如：/UploadFile/2013/06/10/）</param>
        /// <returns></returns>
        public void DeleteDirectory(string directoryPath)
        {
            if (directoryPath.Length > 0)
                if (System.IO.Directory.Exists(GetFullPath(directoryPath)))
                    System.IO.Directory.Delete(GetFullPath(directoryPath));
        }

        /// <summary>
        /// 删除文件（单文件）
        /// </summary>
        /// <param name="filePath">要删除的文件路径和名称（如：/UploadFiles/1.txt）</param>
        /// <returns></returns>
        public void DeleteFile(string filePath)
        {
            if (System.IO.File.Exists(GetFullPath(filePath)))
            {
                RemoveReadOnly(filePath);
                System.IO.File.Delete(GetFullPath(filePath));
            }
        }

        public void DeleteFileZhi(string filePath)
        {
            if (System.IO.File.Exists(filePath))
            {
                System.IO.File.Delete(filePath);
            }
        }

        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="filePath">要删除的文件路径和名称（如：/UploadFiles/1.txt）</param>
        /// <param name="fileContent">文件内容</param>
        /// <returns></returns>
        public void CreateFile(string filePath, string fileContent)
        {
            filePath = filePath.Replace("/", "\\");
            if (filePath.IndexOf("\\") > -1)
                CreateDirectory(filePath.Substring(0, filePath.LastIndexOf("\\")));
            System.IO.StreamWriter sw = new System.IO.StreamWriter(System.Web.HttpContext.Current.Request.PhysicalApplicationPath + "\\" + filePath, false, System.Text.Encoding.GetEncoding("GB2312"));
            sw.Write(fileContent);
            sw.Close();
        }

        /// <summary>
        /// 移动文件
        /// </summary>
        /// <param name="oldFilePath">要移动的文件的路径及全名（包括后缀，如：/UploadFiles/qinbo.bat）</param>
        /// <param name="newFilePath">文件移动到新的位置，并指定新的文件名（如：/UploadFiles/2014/qinbo.bat）</param>
        /// <returns></returns>
        public void MoveFile(string oldFilePath, string newFilePath)
        {
            oldFilePath = oldFilePath.Replace("/", "\\");
            newFilePath = newFilePath.Replace("/", "\\");
            if (newFilePath.IndexOf("\\") > -1)
                CreateDirectory(newFilePath.Substring(0, newFilePath.LastIndexOf("\\")));
            if (System.IO.File.Exists(System.Web.HttpContext.Current.Request.PhysicalApplicationPath + "\\" + oldFilePath))
                System.IO.File.Move(System.Web.HttpContext.Current.Request.PhysicalApplicationPath + "\\" + oldFilePath, System.Web.HttpContext.Current.Request.PhysicalApplicationPath + "\\" + newFilePath);
        }

        /// <summary>
        /// 复制文件
        /// </summary>
        /// <param name="oldFilePath">要复制的文件的路径已经全名（包括后缀，如：/UploadFiles/qinbo.bat）</param>
        /// <param name="newFilePath">目标位置，并指定新的文件名（如：/UploadFiles/2014/qinbo.bat）</param>
        /// <returns></returns>
        public void CopyFile(string oldFilePath, string newFilePath)
        {
            oldFilePath = oldFilePath.Replace("/", "\\");
            newFilePath = newFilePath.Replace("/", "\\");
            if (newFilePath.IndexOf("\\") > -1)
                CreateDirectory(newFilePath.Substring(0, newFilePath.LastIndexOf("\\")));
            if (System.IO.File.Exists(System.Web.HttpContext.Current.Request.PhysicalApplicationPath + "\\" + oldFilePath))
            {
                System.IO.File.Copy(System.Web.HttpContext.Current.Request.PhysicalApplicationPath + "\\" + oldFilePath, System.Web.HttpContext.Current.Request.PhysicalApplicationPath + "\\" + newFilePath, true);
            }
        }

        /// <summary>
        /// 获取文件的名称（包括扩展名称）
        /// </summary>
        /// <param name="filePath">文件的路径名称（如：/UploadFiles/2014/qinbo.bat）</param>
        /// <param name="getType">获取的类型（1：后缀名称，2：前缀名称，3：全部名称）</param>
        /// <returns></returns>
        public string GetFileName(string filePath, int getType)
        {
            System.IO.FileInfo fi = new System.IO.FileInfo(GetFullPath(filePath));
            string strResult = string.Empty;
            string strFullName = fi.Name;
            if (getType.Equals(1)) strResult = strFullName.Substring(strFullName.LastIndexOf('.'), strFullName.Length - strFullName.LastIndexOf('.'));
            else if (getType.Equals(2)) strResult = strFullName.Substring(0, strFullName.LastIndexOf('.'));
            else if (getType.Equals(3)) strResult = strFullName;
            return strResult;
        }

        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="originalImagePath">源图路径（物理路径）</param>
        /// <param name="thumbnailPath">缩略图路径（物理路径）</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="mode">生成缩略图的方式</param>
        public void MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height, string mode)
        {
            originalImagePath = HttpContext.Current.Server.MapPath(originalImagePath);
            thumbnailPath = HttpContext.Current.Server.MapPath(thumbnailPath);
            System.Drawing.Image originalImage = System.Drawing.Image.FromFile(originalImagePath);

            int towidth = width;
            int toheight = height;

            int x = 0;
            int y = 0;
            int ow = originalImage.Width;
            int oh = originalImage.Height;

            switch (mode)
            {
                case "HW"://指定高宽缩放（可能变形）                
                    break;
                case "W"://指定宽，高按比例
                    if (originalImage.Width < width)
                    {
                        towidth = originalImage.Width;
                        toheight = originalImage.Height;
                    }
                    else
                    {
                        toheight = originalImage.Height * width / originalImage.Width;
                    }
                    break;
                case "H"://指定高，宽按比例
                    if (originalImage.Height < height)
                    {
                        toheight = originalImage.Height;
                        towidth = originalImage.Width;
                    }
                    else
                    {
                        towidth = originalImage.Width * height / originalImage.Height;
                    }
                    break;
                case "Cut"://指定高宽裁减（不变形）                
                    if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight)
                    {
                        oh = originalImage.Height;
                        ow = originalImage.Height * towidth / toheight;
                        y = 0;
                        x = (originalImage.Width - ow) / 2;
                    }
                    else
                    {
                        ow = originalImage.Width;
                        oh = originalImage.Width * height / towidth;
                        x = 0;
                        y = (originalImage.Height - oh) / 2;
                    }
                    break;
                default:
                    break;
            }

            //新建一个bmp图片
            System.Drawing.Image bitmap = new System.Drawing.Bitmap(towidth, toheight);

            //新建一个画板
            System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap);

            //设置高质量插值法
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

            //设置高质量,低速度呈现平滑程度
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            //清空画布并以透明背景色填充
            g.Clear(System.Drawing.Color.Transparent);

            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new System.Drawing.Rectangle(0, 0, towidth, toheight),
                new System.Drawing.Rectangle(x, y, ow, oh),
                System.Drawing.GraphicsUnit.Pixel);

            try
            {
                string Path = string.Empty;
                if (thumbnailPath.LastIndexOf("\\") > -1)
                {
                    Path = thumbnailPath.Substring(0, thumbnailPath.LastIndexOf('\\'));
                }
                else
                {
                    Path = thumbnailPath;
                }
                if (!Directory.Exists(Path))
                {
                    Directory.CreateDirectory(Path);
                }

                //以jpg格式保存缩略图
                bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Png);
            }
            catch (System.Exception e)
            {
                throw e;
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }
        }


    }
}
